# coding=utf-8
# fact_electronica_afip
# este es basado en el desarrollo factura_electronica, de Luis Falcon
# pero se han hecho las modificaciones para adecuarlo a la resolucion
# RG 2485 y conectar
# directamente a los web services de AFIP de acuerdo a WSFEV1
# usando el desarrollo pyafipws, de Mariano Reingart
# (C) Gerardo Allende / Daniel Blanco
# GPL - GNU Public License


# Están muchos valores de importe con valor absoluto, puesto que el CAE
# en AFIP no acepta valores negativos.


import wizard
from osv import fields,osv
import pooler
import base64
import string
import StringIO
from xml.dom.minidom import getDOMImplementation
import time
import math
from tools.misc import debug



# Traduce el numero codigo standard de provincia al codigo de la AFIP
def map_provincia_id (codigo):
	afip_code = {'C':1,'B':2,'K':3,'X':4,'W':5,'H':6,'U':7,'E':8,'P':9,'Y':10,'L':11,'F':12,'M':13,'N':14,'Q':15,'R':16,'A':17,'J':18,'D':19,'Z':20,'S':21,'G':22,'V':23,'T':24}	

	return (afip_code [codigo])

# Selecciona la direccion que aparece en el documento de la factura.
# En el caso de la dirección de la empresa, seleccionaremos la dirección predeterminada (default)

def get_partner_address (partneraddrid, partner, cr):
	sql='select street, street2, city, state_id, zip, phone, email from res_partner_address where id='+str(partneraddrid)
	if partner == 'empresa':
		sql='select street, street2, city, state_id, zip, phone, email from res_partner_address where type=\'default\' and partner_id='+str(partneraddrid)
		cr.execute(sql)
		direccion = cr.fetchone()
	sql = 'select code from res_country_state where id='+str(direccion[3])
	cr.execute(sql)
	provincia = cr.fetchone()
	codigo_provincia = provincia[0]
	codigo_afip =  map_provincia_id (codigo_provincia)
#   Pasamos de tuple a list
	b=[]
	for i in direccion:
		b.append(i)
	b[3] = codigo_afip
	return (b)


def get_iibb (partner_id,cr):
	sql='select iibb from res_partner where id='+partner_id
	cr.execute(sql)
	iibb = cr.fetchone()
	return (str(iibb[0]))

def get_razon_social (partner_id,cr):
	sql='select name from res_partner where id='+partner_id
	cr.execute(sql)
	razon_social = cr.fetchone()
	return (str(razon_social[0]))

def get_condicion_iibb (partner_id,cr):
	sql='select cond_iibb from res_partner where id='+partner_id
	cr.execute(sql)
	cond_iibb = cr.fetchone()
	return (str(cond_iibb[0]))

def get_condicion_iva (partner_id,cr):
	sql='select cond_iva from res_partner where id='+partner_id
	cr.execute(sql)
	cond_iva = cr.fetchone()
	return (str(cond_iva[0]))

def code_date (fecha):
	fecha1 = time.strptime (fecha,"%Y-%m-%d")
	return (time.strftime ("%Y%m%d", fecha1))

def get_cuit_empresa (partner_id,cr):
	sql='select vat from res_partner where id='+partner_id
	cr.execute(sql)
	cuit_empresa = cr.fetchone()
	return (str(cuit_empresa[0]))

def get_address_id (invoice_id,cr):
	sql='select address_invoice_id from account_invoice where id='+str(invoice_id)
	cr.execute(sql)
	address_id = cr.fetchone()
	return (address_id[0])

# Extraemos el ID de empresa vendedora en la factura (que puede o no ser el mismo que mi compañia)

def get_vendor_id (invoice_id,cr):
	sql='select company_id from account_invoice where id='+str(invoice_id)
	cr.execute(sql)
	vendor_id = cr.fetchone()
	return (vendor_id[0])


def get_cuit_canal(partner_id,cr):
	sql='select cuit_canal from res_partner where id='+partner_id
	cr.execute(sql)
	cuit_canal = cr.fetchone()
	return (str(cuit_canal[0]))

def get_sucursal_emisora(partner_id,cr):
	sql='select sucursal_emisora from res_partner where id='+partner_id
	cr.execute(sql)
	sucursal_emisora = cr.fetchone()
	return (str(sucursal_emisora[0]))

def get_rubro (partner_id,cr):
	sql='select servicios from res_partner where id='+partner_id
	cr.execute(sql)
	brinda_servicios = 0
	rubro = cr.fetchone()
	if rubro[0]:
		brinda_servicios=1
	return (str (brinda_servicios))

def mypartner_id (inv_id,cr):
	sql='select partner_id from account_invoice where id='+str(inv_id)
	cr.execute(sql)
	mypartnerid = cr.fetchone()
	return (str(mypartnerid[0]))

def mycompany_id (cr):
	sql='select partner_id from res_company'
	cr.execute(sql)
	myid = cr.fetchone()
	return (str (myid[0]))

# esta funcion sirve para obtener mi cuit y que no haga falta fijarlo por codigo. En lugar de tomarlo de res_company,
# lo toma del account invoice para esta factura que estamos autorizando
# despues veremos como se hace para que tambien levante de la base las claves en lugar de tomar archivos
def mycuit (cr):
        sql='select e.vat from res_partner e join account_invoice er on e.id = er.company_id where id='+str(inv_id)
        cr.execute(sql)
        myid = cr.fetchone()
	cuit_con_guion = str(myid[0])
        cuit_sin_guion = cuit_con_guion.replace('-', '')
        return (cuit_con_guion)

# esta es la que calcula el digito verificador
def digito_veri (codigo):
    # Ver RG 1702 AFIP
    # Etapa 1: comenzar desde la izquierda, sumar todos los caracteres ubicados en las posiciones impares.
    etapa1 = sum([int(c) for i,c in enumerate(codigo) if not i%2])
    # Etapa 2: multiplicar la suma obtenida en la etapa 1 por el número 3
    etapa2 = etapa1 * 3
    # Etapa 3: comenzar desde la izquierda, sumar todos los caracteres que están ubicados en las posiciones pares.
    etapa3 = sum([int(c) for i,c in enumerate(codigo) if i%2])
    # Etapa 4: sumar los resultados obtenidos en las etapas 2 y 3.
    etapa4 = etapa2 + etapa3
    # Etapa 5: buscar el menor número que sumado al resultado obtenido en la etapa 4 dé un número múltiplo de 10. 
    # Este será el valor del dígito verificador del módulo 10.
    digito = 10 - (etapa4 - (int(etapa4 / 10) * 10))
    if digito == 10:
        digito = 0
    return str(digito)


generar_cae_form = """<?xml version="1.0"?>
<form string="guardar Formulario de CAE">
		<separator colspan="4" string="Nombre del Archivo" />
		<field name="archivo_destino" />
</form>
"""

generar_cae_fields = {
	'archivo_destino' : {'string':'Archivo:', 'type': 'binary','readonly': True}
}


def _genera_cabecera_lote (invoices,cr, doc,lote_comprobantes, temp_buffer):

#   Numero unico ( fecha + hora )
	fecha_actual = time.localtime ()
	numero_lote = time.strftime ("%Y%m%d%H%M%S", fecha_actual)
	fecha_lote = time.strftime ("%Y%m%d %H%M%S", fecha_actual)
	
	numero_de_comprobantes = str (len (invoices))

	myid = mycompany_id (cr)


	cuit_del_canal = get_cuit_canal(myid,cr)

	
# CABECERA

	cabecera_lote = doc.createElement ("cabecera_lote")
	lote_comprobantes.appendChild (cabecera_lote)

	id_lote = doc.createElement ("id_lote")
	cabecera_lote.appendChild (id_lote)
	valor = doc.createTextNode(numero_lote)
	id_lote.appendChild (valor)

	cuit_canal = doc.createElement ("cuit_canal")
	cabecera_lote.appendChild (cuit_canal)
	valor = doc.createTextNode(cuit_del_canal)
	cuit_canal.appendChild (valor)

	cuit_vendedor = doc.createElement ("cuit_vendedor")
	cabecera_lote.appendChild (cuit_vendedor)
	valor = doc.createTextNode (get_cuit_empresa(myid,cr))
	cuit_vendedor.appendChild (valor)

	cantidad_reg = doc.createElement ("cantidad_reg")
	cabecera_lote.appendChild (cantidad_reg)
	valor = doc.createTextNode (numero_de_comprobantes)
	cantidad_reg.appendChild (valor)

	presta_serv = doc.createElement ("presta_serv")
	cabecera_lote.appendChild (presta_serv)
	valor = doc.createTextNode (get_rubro(myid,cr))
	presta_serv.appendChild (valor)

	fecha_envio_lote = doc.createElement ("fecha_envio_lote")
	cabecera_lote.appendChild (fecha_envio_lote)
	valor = doc.createTextNode (str (fecha_lote))
	fecha_envio_lote.appendChild (valor)

	punto_de_venta = doc.createElement ("punto_de_venta")
	cabecera_lote.appendChild (punto_de_venta)
	valor = doc.createTextNode (str(get_sucursal_emisora(myid,cr)))
	punto_de_venta.appendChild (valor)
	
	
	return ()


def _genera_cuerpo_comprobante (invoice,cr, doc,lote_comprobantes, comprobante, temp_buffer):

	## COMPROBANTE
	
	inv_id = invoice.id
	
	mypartnerid = mypartner_id (inv_id,cr)
	myid = mycompany_id (cr)

	vendorid = get_vendor_id (inv_id ,cr)
	
	partneraddrid = get_address_id (inv_id,cr)
	
	direccion_partner = get_partner_address (partneraddrid,'',cr)
	
	direccion_vendedor = get_partner_address (vendorid,'empresa',cr)

	cabecera = doc.createElement ("cabecera")
	comprobante.appendChild (cabecera)

	informacion_comprobante = doc.createElement ("informacion_comprobante")
	cabecera.appendChild (informacion_comprobante)


	tipo_de_comprobante = doc.createElement ("tipo_de_comprobante")
	informacion_comprobante.appendChild (tipo_de_comprobante)
	valor = doc.createTextNode (str(invoice.tipo_comprobante) )
	tipo_de_comprobante.appendChild (valor)

	numero_comprobante = doc.createElement ("numero_comprobante")
	informacion_comprobante.appendChild (numero_comprobante)
	## Quitamos la parte delantera de la secuencia, delimitada por "-"

	temp_val = str(invoice.number).split('-')
	if len(temp_val) > 1:
		valor = doc.createTextNode (str(temp_val[1]))
	else:
		valor = doc.createTextNode (str(temp_val[0]))

	numero_comprobante.appendChild (valor)


	punto_de_venta = doc.createElement ("punto_de_venta")
	informacion_comprobante.appendChild (punto_de_venta)
	valor = doc.createTextNode (str(invoice.sucursal.name))
	punto_de_venta.appendChild (valor)


	fecha_emision = doc.createElement ("fecha_emision")
	informacion_comprobante.appendChild (fecha_emision)
	valor = doc.createTextNode (code_date (invoice.date_invoice))
	fecha_emision.appendChild (valor)
	
	fecha_vencimiento = doc.createElement ("fecha_vencimiento")
	informacion_comprobante.appendChild (fecha_vencimiento)
	valor = doc.createTextNode (code_date (invoice.date_due))
	fecha_vencimiento.appendChild (valor)

	fecha_servdesde = doc.createElement ("fecha_serv_desde")
	informacion_comprobante.appendChild (fecha_servdesde)
	valor = doc.createTextNode (code_date (invoice.serv_fecha_desde))
	fecha_servdesde.appendChild (valor)

	fecha_servhasta = doc.createElement ("fecha_serv_hasta")
	informacion_comprobante.appendChild (fecha_servhasta)
	valor = doc.createTextNode (code_date (invoice.serv_fecha_hasta))
	fecha_servhasta.appendChild (valor)

	es_detalle_encriptado = doc.createElement ("es_detalle_encriptado")
	informacion_comprobante.appendChild (es_detalle_encriptado)
	valor = doc.createTextNode ("N")
	es_detalle_encriptado.appendChild (valor)


	## Vendedor

	informacion_vendedor = doc.createElement ("informacion_vendedor")
	cabecera.appendChild (informacion_vendedor)

	razon_social = doc.createElement ("razon_social")
	informacion_vendedor.appendChild (razon_social)
	valor = doc.createTextNode (unicode (get_razon_social (myid, cr),'utf-8'))
	razon_social.appendChild (valor)

	cuit = doc.createElement ("cuit")
	informacion_vendedor.appendChild (cuit)
	valor = doc.createTextNode (get_cuit_empresa(myid,cr))
	cuit.appendChild (valor)

	condicion_IVA = doc.createElement ("condicion_IVA")
	informacion_vendedor.appendChild (condicion_IVA)
	valor = doc.createTextNode (get_condicion_iva (myid,cr))
	condicion_IVA.appendChild (valor)

	condicion_ingresos_brutos = doc.createElement ("condicion_ingresos_brutos")
	informacion_vendedor.appendChild (condicion_ingresos_brutos)
	valor = doc.createTextNode (get_condicion_iibb (myid,cr))
	condicion_ingresos_brutos.appendChild (valor)

	nro_ingresos_brutos = doc.createElement ("nro_ingresos_brutos")
	informacion_vendedor.appendChild (nro_ingresos_brutos)
	valor = doc.createTextNode (get_iibb(myid,cr))
	nro_ingresos_brutos.appendChild (valor)

	domicilio_calle = doc.createElement ("domicilio_calle")
	informacion_vendedor.appendChild (domicilio_calle)
	valor = doc.createTextNode (unicode (str(direccion_vendedor[0]),'utf-8'))
	domicilio_calle.appendChild (valor)

	localidad = doc.createElement ("localidad")
	informacion_vendedor.appendChild (localidad)
	valor = doc.createTextNode (unicode (str(direccion_vendedor[2]),'utf-8'))
	localidad.appendChild (valor)

	provincia = doc.createElement ("provincia")
	informacion_vendedor.appendChild (provincia)
	valor = doc.createTextNode (unicode (str(direccion_vendedor[3]),'utf-8'))
	provincia.appendChild (valor)

	cp = doc.createElement ("cp")
	informacion_vendedor.appendChild (cp)
	valor = doc.createTextNode (str(direccion_vendedor[4]))
	cp.appendChild (valor)

	email = doc.createElement ("email")
	informacion_vendedor.appendChild (email)
	valor = doc.createTextNode (str(direccion_vendedor[6]))
	email.appendChild (valor)

	telefono = doc.createElement ("telefono")
	informacion_vendedor.appendChild (telefono)
	valor = doc.createTextNode (str(direccion_vendedor[5]))
	telefono.appendChild (valor)

	## Comprador

	informacion_comprador = doc.createElement ("informacion_comprador")
	cabecera.appendChild (informacion_comprador)

	codigo_doc_identificatorio = doc.createElement ("codigo_doc_identificatorio")
	informacion_comprador.appendChild (codigo_doc_identificatorio)
	valor = doc.createTextNode (str(invoice.id_type.name))
	codigo_doc_identificatorio.appendChild (valor)

	nro_doc_identificatorio = doc.createElement ("nro_doc_identificatorio")
	informacion_comprador.appendChild (nro_doc_identificatorio)
	valor = doc.createTextNode (get_cuit_empresa (mypartnerid,cr))
	nro_doc_identificatorio.appendChild (valor)

	denominacion = doc.createElement ("denominacion")
	informacion_comprador.appendChild (denominacion)
	valor = doc.createTextNode (unicode (get_razon_social (mypartnerid,cr),'utf-8'))
	denominacion.appendChild (valor)


	domicilio_calle = doc.createElement ("domicilio_calle")
	informacion_comprador.appendChild (domicilio_calle)
	valor = doc.createTextNode (unicode (str(direccion_partner[0]),'utf-8'))
	domicilio_calle.appendChild (valor)

	localidad = doc.createElement ("localidad")
	informacion_comprador.appendChild (localidad)
	valor = doc.createTextNode (unicode (str(direccion_partner[2]),'utf-8'))
	localidad.appendChild (valor)

	provincia = doc.createElement ("provincia")
	informacion_comprador.appendChild (provincia)
	valor = doc.createTextNode (unicode (str(direccion_partner[3]),'utf-8'))
	provincia.appendChild (valor)

	cp = doc.createElement ("cp")
	informacion_comprador.appendChild (cp)
	valor = doc.createTextNode (unicode (str(direccion_partner[4]),'utf-8'))
	cp.appendChild (valor)

	
	return ()


def _genera_detalle_factura (lineafact,cr, doc,lote_comprobantes, comprobante, detalle, nro_linea, temp_buffer):


	linea = doc.createElement ("linea")
	detalle.appendChild (linea)
	linea.setAttribute ("numeroLinea",str (nro_linea))


	descripcion = doc.createElement ("descripcion")
	linea.appendChild (descripcion)
	valor = doc.createTextNode (unicode (str(lineafact.name),'utf-8'))
	descripcion.appendChild (valor)

	cantidad = doc.createElement ("cantidad")
	linea.appendChild (cantidad)
	valor = doc.createTextNode (str(lineafact.quantity))
	cantidad.appendChild (valor)

	precio_unitario = doc.createElement ("precio_unitario")
	linea.appendChild (precio_unitario)
	valor = doc.createTextNode (str(abs(lineafact.price_unit)))
	precio_unitario.appendChild (valor)

	importe_total_articulo = doc.createElement ("importe_total_articulo")
	linea.appendChild (importe_total_articulo)
	valor = doc.createTextNode (str(abs(lineafact.price_subtotal)))
	importe_total_articulo.appendChild (valor)

# El valor que aparece como código de impuesto será multiplicado la cantidad por 100

	alicuota_iva = doc.createElement ("alicuota_iva")
	linea.appendChild (alicuota_iva)
	
	tasa_impuesto = [ t.amount for t in lineafact.invoice_line_tax_id ]
	
	valor = doc.createTextNode (str(tasa_impuesto[0]*100))
	alicuota_iva.appendChild (valor)

	return ()


def _genera_resumen_factura (invoice,cr, doc,lote_comprobantes, comprobante, temp_buffer):
#   GENERA EL RESUMEN DE CADA FACTURA

	resumen = doc.createElement ("resumen")
	comprobante.appendChild (resumen)

	importe_total_neto_gravado = doc.createElement ("importe_total_neto_gravado")
	resumen.appendChild (importe_total_neto_gravado)
	valor = doc.createTextNode (str("%.2f" % abs(invoice.amount_untaxed)))
	importe_total_neto_gravado.appendChild (valor)
	
	importe_total_concepto_no_gravado = doc.createElement ("importe_total_concepto_no_gravado")
	resumen.appendChild (importe_total_concepto_no_gravado)
	valor = doc.createTextNode ("0.00")
	importe_total_concepto_no_gravado.appendChild (valor)

	importe_operaciones_exentas = doc.createElement ("importe_operaciones_exentas")
	resumen.appendChild (importe_operaciones_exentas)
	valor = doc.createTextNode ("0.00")
	importe_operaciones_exentas.appendChild (valor)

	impuesto_liq = doc.createElement ("impuesto_liq")
	resumen.appendChild (impuesto_liq)
	valor = doc.createTextNode (str("%.2f" % abs(invoice.amount_tax)))
	impuesto_liq.appendChild (valor)

	impuesto_liq_rni = doc.createElement ("impuesto_liq_rni")
	resumen.appendChild (impuesto_liq_rni)
	valor = doc.createTextNode ("0.00")
	impuesto_liq_rni.appendChild (valor)

	importe_total_impuestos_nacionales = doc.createElement ("importe_total_impuestos_nacionales")
	resumen.appendChild (importe_total_impuestos_nacionales)
	valor = doc.createTextNode ("0.00")
	importe_total_impuestos_nacionales.appendChild (valor)

	importe_total_ingresos_brutos = doc.createElement ("importe_total_ingresos_brutos")
	resumen.appendChild (importe_total_ingresos_brutos)
	valor = doc.createTextNode ("0.00")
	importe_total_ingresos_brutos.appendChild (valor)

	importe_total_impuestos_municipales = doc.createElement ("importe_total_impuestos_municipales")
	resumen.appendChild (importe_total_impuestos_municipales)
	valor = doc.createTextNode ("0.00")
	importe_total_impuestos_municipales.appendChild (valor)

	importe_total_impuestos_internos = doc.createElement ("importe_total_impuestos_internos")
	resumen.appendChild (importe_total_impuestos_internos)
	valor = doc.createTextNode ("0.00")
	importe_total_impuestos_internos.appendChild (valor)


	importe_total_factura = doc.createElement ("importe_total_factura")
	resumen.appendChild (importe_total_factura)
	valor = doc.createTextNode (str("%.2f" % abs(invoice.amount_total)))
	importe_total_factura.appendChild (valor)

	tipo_de_cambio = doc.createElement ("tipo_de_cambio")
	resumen.appendChild (tipo_de_cambio)
	valor = doc.createTextNode (str(invoice.currency_id.rate))
	tipo_de_cambio.appendChild (valor)

	codigo_moneda = doc.createElement ("codigo_moneda")
	resumen.appendChild (codigo_moneda)
	valor = doc.createTextNode (str(invoice.currency_id.afip))
	codigo_moneda.appendChild (valor)

	observaciones = doc.createElement ("observaciones")
	resumen.appendChild (observaciones)
	if invoice.comment == 0:
		temp_val = '' 
	else :
		temp_val = invoice.comment
		valor = doc.createTextNode (str(temp_val))
		observaciones.appendChild (valor)


	return ()


def _generar_archivo (self, cr, uid, data, context):
	
	invoice_table=pooler.get_pool(cr.dbname).get('account.invoice')
	invoices = invoice_table.browse(cr, uid, data['ids'])
	
	temp_buffer = StringIO.StringIO()
	
	
	
	#return {'archivo_destino': ""}
	
	
#EMPIEZA PARTE DE PYAFIPWS 
	
	import os, time
	import datetime
	import decimal
	import os
	import socket
	import sys
	import traceback
	from pyafipws.pysimplesoap.client import SimpleXMLElement, SoapClient, SoapFault, parse_proxy, set_http_wrapper

	from pyafipws import wsfev1 as w
	DEBUG = True

	if DEBUG:
		from pyafipws.pysimplesoap.client import __version__ as soapver
		print "pysimplesoap.__version__ = ", soapver

	wsfev1 = w.WSFEv1()

	cache = None
	#wsdl = "https://servicios1.afip.gov.ar/wsfev1/service.asmx" # Produccion
	wsdl = "https://wswhomo.afip.gov.ar/wsfev1/service.asmx?WSDL" # Homologacion
	proxy = ""
	wrapper = "" #"pycurl"
	cacert = os.path.join(wsfev1.InstallDir, "geotrust.crt")

	wsfev1.Conectar(cache, wsdl, proxy, wrapper, cacert)

	if DEBUG:
		print "LOG: ", wsfev1.DebugLog()
		
	print wsfev1.client.help("FEDummy")
	wsfev1.Dummy()
	print "AppServerStatus", wsfev1.AppServerStatus
	print "DbServerStatus", wsfev1.DbServerStatus
	print "AuthServerStatus", wsfev1.AuthServerStatus

	if wsfev1.AppServerStatus != 'OK':
		raise wizard.except_wizard('Error !', 'El servidor de aplicaciones de la AFIP no está funcionando correctamente.')
	
	if wsfev1.DbServerStatus != 'OK':
		raise wizard.except_wizard('Error !', 'El servidor de base de datos de la AFIP no está funcionando correctamente.')

	if wsfev1.AuthServerStatus != 'OK':
		raise wizard.except_wizard('Error !', 'El servidor de autenticación de la AFIP no está funcionando correctamente.')
	
	# obteniendo el TA
	TA = os.path.join(wsfev1.InstallDir, "TA-wsfe.xml")
	if not os.path.exists(TA) or os.path.getmtime(TA)+(60*60*5)<time.time():
		from pyafipws import wsaa
		tra = wsaa.create_tra(service="wsfe")
		crtfile = os.path.join(wsfev1.InstallDir, "reingart.crt")
		keyfile = os.path.join(wsfev1.InstallDir, "reingart.key")
		cms = wsaa.sign_tra(tra,crtfile,keyfile)
		#url = "https://wsaa.afip.gov.ar/ws/services/LoginCms" # producción
		url = "" # homologación
		ta_string = wsaa.call_wsaa(cms, url)
		open(TA,"w").write(ta_string)
		print 'Tra: ',tra
	ta_string=open(TA).read()
	ta = SimpleXMLElement(ta_string)
	# fin TA
	print 'Ta String: ',ta_string
	
	myid = mycompany_id (cr)	
	
	wsfev1.Cuit = get_cuit_empresa(myid,cr).replace('-','')
	print wsfev1.Cuit
	wsfev1.Token = str(ta.credentials.token)
	wsfev1.Sign = str(ta.credentials.sign)
	
	#Pedimos CAE por cada factura del lote
	for invoice in invoices:
		
		
		print wsfev1.client.help("FECAESolicitar").encode("latin1")
		#print "Procesando factura Nº"
		
		inv_id = invoice.id
		mypartnerid = mypartner_id (inv_id,cr)
		
		tipo_cbte = invoice.tipo_comprobante
		print "tipo_cbte",tipo_cbte
		
		if tipo_cbte == 'C':
			tipo_cbte=11
		elif tipo_cbte == 'M':
			raise wizard.except_wizard('Error !', 'Facturas M no implementadas')
		elif tipo_cbte == 'E':
			raise wizard.except_wizard('Error !', 'Facturas E no implementadas')
			
		tipo_cbte=long(tipo_cbte)
		 
		temp_val = str(invoice.number).split('-')
		if len(temp_val) > 1:
			cbte_nro = long(temp_val[1])
		else:
			cbte_nro = long(temp_val[0])
		
		punto_vta=long(invoice.sucursal.name)
		print 'punto_vta',punto_vta
		
		if invoice.cae:
			print "La factura Nº",invoice.number, "de", get_razon_social(mypartnerid,cr), "ya tiene CAE."
			continue
			
		#Verificamos que el número de comprobante sea válido
		cbte_nro_afip=long(wsfev1.CompUltimoAutorizado(tipo_cbte, punto_vta) or 0)+1
		
		print wsfev1.XmlResponse
		
		print 'cbte_nro_afip',cbte_nro_afip
		print 'cbte_nro',cbte_nro
		if cbte_nro != cbte_nro_afip:
			temp_val=get_razon_social(mypartnerid,cr)
			raise wizard.except_wizard('Error !', 'Referencia: ' + temp_val + ' ' + 
				str(invoice.number) + '\nEl número del comprobante debería ser ' + 
				str(cbte_nro_afip) + ' y no ' + str(cbte_nro) + '.' )
		
		
		cbte_nro = cbte_nro_afip
		fecha = datetime.datetime.now().strftime("%Y%m%d")
		concepto = long(invoice.concepto_factura)
		if concepto==0:
			concepto=3
			#TO DO: Esto no se porque no funca.
			#cr.execute("UPDATE account_invoice SET concepto_factura=%s WHERE id=%s", (concepto,invoice.id))
			
		print 'concepto',concepto
		print '-'*20
		
		#code_date (invoice.date_invoice)
		#code_date (invoice.date_due)
		
		 #codigo_doc_identificatorio
		

		fecha_cbte = fecha
		fecha_venc_pago = fecha
		# Fechas del período del servicio facturado (solo si concepto = 1?)
		if concepto==1:
			fecha_serv_desde = fecha
			fecha_serv_hasta = fecha
		else:
			fecha_serv_desde = code_date (invoice.serv_fecha_desde)
			fecha_serv_hasta = code_date (invoice.serv_fecha_hasta)


		tipo_doc = long(invoice.id_type.name)
		nro_doc = get_cuit_empresa (mypartnerid,cr).replace("-","")
		
		cbt_desde = cbte_nro; cbt_hasta = cbte_nro
		
		imp_total = str("%.2f" % abs(invoice.amount_total))
		imp_tot_conc = "0.00"
		imp_neto = str("%.2f" % abs(invoice.amount_untaxed))
		imp_iva = str("%.2f" % abs(invoice.amount_tax))
		imp_trib = "0.00"
		imp_op_ex = "0.00"
		moneda_id = str(invoice.currency_id.afip)
		moneda_ctz = str(invoice.currency_id.rate)

		wsfev1.CrearFactura(concepto, tipo_doc, nro_doc, tipo_cbte, punto_vta,
			cbt_desde, cbt_hasta, imp_total, imp_tot_conc, imp_neto,
			imp_iva, imp_trib, imp_op_ex, fecha_cbte, fecha_venc_pago, 
			fecha_serv_desde, fecha_serv_hasta,
			moneda_id, moneda_ctz)
		
		#TO DO:
		#COMPROBANTE ASOCIADO EN CASO DE NOTA DEBITO O NOTA CREDITO DE DONDE SACO ESE DATO EN OPENERP	
		
		for linea_impuesto in invoice.tax_line:
			if linea_impuesto.name=='5 - IVA Ventas 21%':
				impuesto_id = 5
			elif linea_impuesto.name=='4 - IVA Ventas 10,5%':
				impuesto_id = 4
			else:
				relacion = linea_impuesto.amount/linea_impuesto.base * 100
				if relacion < 9:
					impuesto_id = 3 # IVA 0%
				elif 9 <= relacion < 19:
					impuesto_id = 4 # IVA 10,5%
				elif 19 <= relacion < 25:
					impuesto_id = 5 # IVA 21%
				elif 25 <= relacion:
					impuesto_id = 6 # IVA 27%
				
			base_im = ("%.2f" % abs(linea_impuesto.base))
			importe = ("%.2f" % abs(linea_impuesto.amount))
			print "impuesto_id, base_im, importe",impuesto_id, base_im, importe
			wsfev1.AgregarIva(impuesto_id, base_im, importe)
			
		try:	
			wsfev1.CAESolicitar()
		except SoapFault as fault:
			print fault.faultcode
			print fault.faultstring
			open(os.path.join(wsfev1.InstallDir, "xmlrequest.xml"),"wb").write(wsfev1.XmlRequest)
			raise wizard.except_wizard('Error !', 'SoapFault.faultcode = ' + str(fault.faultcode) + 
				'\nSoapFault.faultstring = ' + str(fault.faultstring))
			
		print "Resultado", wsfev1.Resultado
		print "Reproceso", wsfev1.Reproceso
		print "CAE", wsfev1.CAE
		
		open(os.path.join(wsfev1.InstallDir, "xmlrequest.xml"),"wb").write(wsfev1.XmlRequest)
		open(os.path.join(wsfev1.InstallDir, "xmlresponse.xml"),"wb").write(wsfev1.XmlResponse)
		
		wsfev1.AnalizarXml("XmlResponse")
		print wsfev1.ObtenerTagXml('CAE'), str(wsfev1.CAE)
		print wsfev1.ObtenerTagXml('Concepto')
		#print wsfev1.ObtenerTagXml('Obs',0,'Code')
		#print wsfev1.ObtenerTagXml('Obs',0,'Msg')

		if wsfev1.Resultado=='R':
			obs_afip = str(wsfev1.ObtenerTagXml('Obs',0,'Code')) + ' - ' + wsfev1.ObtenerTagXml('Obs',0,'Msg')
			cr.execute('UPDATE account_invoice SET resultado=%s WHERE id=%s', (wsfev1.Resultado, invoice.id))
			cr.execute('UPDATE account_invoice SET cod_error_afip=%s WHERE id=%s', (str(wsfev1.ObtenerTagXml('Obs',0,'Code')), invoice.id))
			temp_val=get_razon_social(mypartnerid,cr)
			#raise wizard.except_wizard('Error !', 'Referencia: ' + temp_val + '\n' + obs_afip )
			print 'Error !', 'Referencia: ' + str(invoice.number) + ' - ' + temp_val + '\n' + obs_afip
		if wsfev1.CAE:
			cr.execute('UPDATE account_invoice SET resultado=%s, cae=%s, fecha_vto_cae=%s  WHERE id=%s', 
				(wsfev1.Resultado, wsfev1.CAE, wsfev1.Vencimiento, invoice.id))
			# a partir de aqui, escrito por daniel para generar el codigo de barras y guardarlo en la base
			# primero solo lo imprimo para ver si lo muestra bien
			codigo_b1 = get_cuit_empresa(myid,cr).replace('-', '')+str(invoice.tipo_comprobante)+str(invoice.sucursal.name)+str(wsfev1.CAE)+str(wsfev1.Vencimiento)
			codigo = codigo_b1+digito_veri(codigo_b1)
			cr.execute('UPDATE account_invoice SET codigo_b=%s WHERE id=%s', 
				(codigo, invoice.id))
			
		

	#wsfev1.sys.argv=["--debug", "--prueba", "--get"]
	#wsfev1.main()  

#   FIN DE LA PARTE DE PYAFIPWS






#   Empezamos a generar el documento XML
#   doc = Nombre del documento XML
#   lote_comprobante = root element con toda la informacion requerida



	#~ impl = getDOMImplementation()
#~ 
	#~ doc = impl.createDocument(None, "lote_comprobantes", None)
#~ 
	#~ lote_comprobantes = doc.documentElement
#~ 
#~ #   Esta linea es solo para usar con INTERFACTURAS  
	#~ lote_comprobantes.setAttributeNS (None, "xmlns","http://lote.schemas.cfe.ib.com.ar/")
#~ 
	#~ _genera_cabecera_lote (invoices,cr, doc, lote_comprobantes,temp_buffer)
#~ 
#~ 
#~ 
	#~ for invoice in invoices:
		#~ comprobante = doc.createElement ("comprobante")
		#~ lote_comprobantes.appendChild (comprobante)
#~ 
	#~ 
		#~ _genera_cuerpo_comprobante (invoice,cr, doc,lote_comprobantes, comprobante, temp_buffer)
		#~ 
		#~ nro_linea=0	 
#~ 
		#~ # DETALLE  -- En Lineas de facturacion (debemos calcular el numero de lineas en este punto )
#~ 
		#~ detalle = doc.createElement ("detalle")
		#~ comprobante.appendChild (detalle)
#~ 
		#~ for lineafact in invoice.invoice_line:
			#~ 
			#~ nro_linea=nro_linea+1
#~ 
			#~ _genera_detalle_factura (lineafact,cr, doc,lote_comprobantes, comprobante, detalle, nro_linea, temp_buffer)
						 #~ 
		#~ _genera_resumen_factura (invoice,cr, doc,lote_comprobantes, comprobante, temp_buffer)
				#~ 
#~ # Cambiamos la codificacion del documento a ISO-8859-1, que parece que es la que usa hoy AFIP
#~ 
	#~ temp_buffer.write (doc.toxml("ISO-8859-1"))
			#~ 
	#~ try:
		#~ contenido_buffer = base64.encodestring(temp_buffer.getvalue())		  
		#~ temp_buffer.close()
#~ 
	#~ except IOError, e:
		#~ raise wizard.except_wizard('Error !', 'No se pudo grabar el archivo:\n'+nombre_archivo+'!')
		#~ 
	#~ return {'archivo_destino': contenido_buffer}
	return {'archivo_destino': ""}



class genera_formulario_cae (wizard.interface):
 states = {
				'init': {
						'actions': [_generar_archivo],
						'result':
				{
								'type': 'form',
								'arch': generar_cae_form,
								'fields': generar_cae_fields,
								'state': [('end','Cancelar'),('finalizar','OK')]
				}
					},
		'finalizar':
			{ 
			'actions': [],
			'result': {'type': 'state', 'state':'end'}
			}

		}


genera_formulario_cae ('factura_electronica.solicitar_cae')

